package cn.jannal.lock.service;

import basic.arch.component.lock.aop.annotation.Lock;
import basic.arch.component.lock.aop.annotation.Lock.DisstributionLockType;
import cn.jannal.lock.dao.ProductStockMapper;
import cn.jannal.lock.exception.BusinessException;
import cn.jannal.lock.pojo.ProductStock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service("productStockService")
public class ProductStockServiceImpl implements ProductStockService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Resource
    private ProductStockMapper productStockMapper;

    /**
     * 通过外围的调用来控制重试次数，就是在多个事务中执行
     */
    public void updateProductNum(Long productId, Long productNum) {
        // 可以在外侧首先查询一次
        ProductStock productStock = productStockMapper.findByProductId(productId);
        if (productStock.getProductNum().longValue() >= productNum.longValue()) {
            int flag = productStockMapper.updateMinusStockByProductId(productNum, productId, productStock.getVersion());
            if (flag != 1) {
                throw new BusinessException("秒杀失败");
            }
        } else {
            throw new BusinessException("商品不足");
        }
    }

    /**
     * 通过内部来控制重试次数，在一个事务中
     */
    public void updateProductNum1(Long productId, Long productNum) {
        ProductStock productStock = null;
        for (int i = 0; i <= 3; i++) {
            productStock = productStockMapper.findByProductId(productId);
            if (productStock.getProductNum().longValue() >= productNum.longValue()) {
                int flag = productStockMapper.updateMinusStockByProductId(productNum, productId, productStock.getVersion());
                if (flag != 1) {
                    if (i == 3) {
                        throw new BusinessException("秒杀失败");
                    } else {
                        logger.warn("进行重试");
                        continue;
                    }
                } else {
                    logger.info("秒杀成功");
                    return;
                }
            } else {
                throw new BusinessException("商品不足");
            }
        }

    }

    public void updateProductNum2(Long productId, Long productNum) {
        ProductStock productStock  = productStockMapper.findByProductId(productId);
        //if (productStock.getProductNum().longValue() > 0) { 会超卖
        if (productStock.getProductNum().longValue() >= productNum.longValue()) {
            int flag = productStockMapper.updateMinusStockByProductId2(productNum, productId, productStock.getVersion());
            if (flag != 1) {
                throw new BusinessException("秒杀出错，商品可能已经售完");
            }
        } else {
            throw new BusinessException("商品不足");
        }
    }

    /**
     * 不查询，只更新
     * @param productId
     * @param productNum
     */
    public void updateProductNum22(Long productId, Long productNum) {
        //ProductStock productStock  = productStockMapper.findByProductId(productId);
        //if (productStock.getProductNum().longValue() > 0) { 会超卖
        /*if (productStock.getProductNum().longValue() >= productNum.longValue()) {
            int flag = productStockMapper.updateMinusStockByProductId3(productNum,productId);
            if (flag != 1) {
                throw new BusinessException("秒杀出错，商品可能已经售完");
            }
        } else {
            throw new BusinessException("商品不足");
        }*/
        int flag = productStockMapper.updateMinusStockByProductId3(productNum,productId);
        if (flag != 1) {
            throw new BusinessException("秒杀出错，商品可能已经售完");
        }
    }

    /**
     * 通过悲观锁
     */
    public void updateProductNum3(Long productId, Long productNum) {

        // 可以在外侧首先查询一次
        ProductStock productStock = productStockMapper.findByIdForUpdate(productId);
        //if (productStock.getProductNum().longValue() >0) {//会超卖
        if (productStock.getProductNum().longValue() >= productNum.longValue()) {
            int flag = productStockMapper.updateMinusStockByProductId(productNum, productId, productStock.getVersion());
            if (flag != 1) {
                throw new BusinessException("秒杀失败");
            }
        } else {
            throw new BusinessException("商品不足");
        }
    }

    @Override
    @Lock(name="productStock",key="#productId",distributeLockMaxWaitTime=5000,disstributionLockType=DisstributionLockType.REDIS)
    public void saveOrUpdate(Long productId, Long productNum) {
        ProductStock productStock = productStockMapper.findByProductId(productId);
        if (productStock == null) {
            productStock = new ProductStock();
            productStock.setProductId(productId);
            productStock.setProductNum(productNum);
            productStock.setVersion(1L);
            int flag = productStockMapper.insert(productStock);
            if (flag != 1) {
                throw new BusinessException("插入失败");
            }
        } else {
            int flag = productStockMapper.updateProductNumById(productNum, productStock.getId());
            if (flag != 1) {
                throw new BusinessException("更新失败");
            }
        }
    }

    @Override
    @Lock(name="productStock",key="#productId",distributeLockMaxWaitTime=5000,disstributionLockType=DisstributionLockType.MYSQL)
    public void saveOrUpdateMysql(Long productId, Long productNum) {
        ProductStock productStock = productStockMapper.findByProductId(productId);
        if (productStock == null) {
            productStock = new ProductStock();
            productStock.setProductId(productId);
            productStock.setProductNum(productNum);
            productStock.setVersion(1L);
            int flag = productStockMapper.insert(productStock);
            if (flag != 1) {
                throw new BusinessException("插入失败");
            }
        } else {
            int flag = productStockMapper.updateProductNumById(productNum, productStock.getId());
            if (flag != 1) {
                throw new BusinessException("更新失败");
            }
        }
        
    }

    @Override
    @Lock(name="productStock",key="#productId",distributeLockMaxWaitTime=5000,disstributionLockType=DisstributionLockType.ZOOKEEPER)
    public void saveOrUpdateZookeeper(Long productId, Long productNum) {
        ProductStock productStock = productStockMapper.findByProductId(productId);
        if (productStock == null) {
            productStock = new ProductStock();
            productStock.setProductId(productId);
            productStock.setProductNum(productNum);
            productStock.setVersion(1L);
            int flag = productStockMapper.insert(productStock);
            if (flag != 1) {
                throw new BusinessException("插入失败");
            }
        } else {
            int flag = productStockMapper.updateProductNumById(productNum, productStock.getId());
            if (flag != 1) {
                throw new BusinessException("更新失败");
            }
        }
        
    }


}
